//
// Created on 2025/7/19.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef STREAMCORE_OBJECT_H
#define STREAMCORE_OBJECT_H
#include <napi/native_api.h>

class NapiObject {
public:
    NapiObject(napi_env env, napi_value value) : env_(env), value_(value) {}

    template <typename T> bool try_get(const char *name, T *value) {
        napi_value p;
        bool has_property = false;

        if (napi_ok != napi_has_named_property(env_, value_, name, &has_property) || !has_property)
            return false;

        if (napi_ok != napi_get_named_property(env_, value_, name, &p))
            return false;
        try {
            *value = As<T>(env_, p);
            return true;
        } catch (...) {
            return false;
        }
    }

    template <typename T> T get(const char *name, T default_value) {
        T value;
        if (try_get(name, &value)) {
            return value;
        }
        return default_value;
    }

    napi_value get(const char *name) {
        napi_value p;
        napi_get_named_property(env_, value_, name, &p);
        return p;
    }

    NapiObject nested(const char *name) { return NapiObject(env_, get(name)); }


    template <typename T> class PropertyProxy {
    public:
        PropertyProxy(napi_env env, napi_value obj, const char *name) : env_(env), obj_(obj), name_(name) {}

        operator T() const {
            napi_value p;
            napi_get_named_property(env_, obj_, name_, &p);
            return As<T>(env_, p);
        }

        PropertyProxy &operator=(const T &value) {
            napi_value js_value = From<T>(env_, value);
            napi_set_named_property(env_, obj_, name_, js_value);
            return *this;
        }

    private:
        napi_env env_;
        napi_value obj_;
        const char *name_;
    };

    template <typename T> PropertyProxy<T> operator[](const char *name) { return PropertyProxy<T>(env_, value_, name); }


private:
    napi_env env_;
    napi_value value_;
};

#endif // STREAMCORE_OBJECT_H
